package org.sxp.common.websocket;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by klaus on 2019/6/12.
 */

@ServerEndpoint(value = "/endpointChat/{sessionId}", configurator=GetHttpSessionConfigurator.class)
@Component
public class WebSocketSession {

    private static final Logger logger = LoggerFactory.getLogger(WebSocketSession.class);
    private static Map<String, WebSocketSession> clients = new ConcurrentHashMap<String, WebSocketSession>();
    private Session session;
    private String userSessionId;
    private static String mark = "_";
    private static String destinationPrefix = "/user";
    private List<String> theme = new ArrayList<>();
    @OnOpen
    public void onOpen(Session session, @PathParam("sessionId") String sessionId, EndpointConfig config) {
////        HttpSession httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
////
////        SimplePrincipalCollection principalCollection = (SimplePrincipalCollection) httpSession
////                .getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
////        SysUserEntity userDO = (SysUserEntity) principalCollection.getPrimaryPrincipal();
//
//        session.setMaxTextMessageBufferSize(1024 * 100 * 5);
//        session.setMaxBinaryMessageBufferSize(1024 * 100 * 5);
        this.userSessionId = sessionId;
        this.session = session;
        clients.put(this.userSessionId, this);
    }

    @OnClose
    public void onClose(Session session) {
        try {
            clients.remove(userSessionId);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        clients.remove(userSessionId);
        try {
            session.close();
        } catch (IOException e) {
            logger.error("close session failed {}", e.getMessage());
        }
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        SimpleTextMsg msgObj = JSON.parseObject(message, SimpleTextMsg.class);
        if(msgObj.getOption().equals(WebSocketClientOption.REGISTER_THEME)){//client在连接成功之后，注册监听主题
            theme.add(msgObj.getTheme());
        }
    }

    public static void convertAndSendToUser(String userId, String theme, String jsonData) {
        synchronized (userId.intern()){
            try{
                for (WebSocketSession item : clients.values()) {
                    String idKey = userId+mark+item.getUserSessionId().split(mark)[1];
                    if (item.getUserSessionId().equals(idKey)){
                        if(item.getTheme().contains(destinationPrefix+theme)){//判断该session的用户是否订阅主题
                            SimpleTextMsg textMsg = new SimpleTextMsg();
                            textMsg.setBody(jsonData);
                            textMsg.setTheme("/user"+theme);
                            item.session.getBasicRemote().sendText(JSON.toJSONString(textMsg));
                        }
                    }
                }
            }catch (Exception e){
                logger.error(e.getMessage(),e);
            }
        }
    }

    public String getUserSessionId() {
        return userSessionId;
    }

    public void setUserSessionId(String userSessionId) {
        this.userSessionId = userSessionId;
    }

    public List<String> getTheme() {
        return theme;
    }

    public void setTheme(List<String> theme) {
        this.theme = theme;
    }

    public static Map<String, WebSocketSession> getClients() {
        return clients;
    }
}
